#pragma once
#include "Common.h"
#include "ThreadCache.h"
#include "PageCache.h"
#include "ObjectPool.h"
#include "CentralCache.h"

static void *ConcurrentAlloc(size_t size)
{
	//需要大块内存，大于256k，也就是32页
	if (size > MAX_BYTES)
	{
		//由于PageCache最大为128页，因此直接向PageCache要会比直接向三层缓存快
		//但是如果大于128页，则需要向堆申请

		//对齐
		size_t alignSize = GetObjSizeClass::RoundUp(size);
		//页号
		size_t kpage = alignSize >> PAGE_SHIFT;

		PageCache::GetInstance()->GetMutex().lock();
		Span *span = PageCache::GetInstance()->NewSpan(kpage);
		span->_objSize = size;
		PageCache::GetInstance()->GetMutex().unlock();

		void *ptr = (void *)(span->_pageId << PAGE_SHIFT);
		return ptr;
	}
	//小于256k，直接向三层缓存要
	else
	{
		if (pTLSThreadCache == nullptr)
		{
			static ObjectPool<ThreadCache> _tcPool;
			// pTLSThreadCache = new ThreadCache;
			pTLSThreadCache = _tcPool.New();
		}
		return pTLSThreadCache->Allocate(size);
	}
}
// static void ConcurrentFree(void* ptr,size_t size)
static void ConcurrentFree(void *ptr)
{
	//获取ptr对应的span，然后获取其size
	Span *span = PageCache::GetInstance()->MapObjectToSpan(ptr);
	size_t size = span->_objSize;
	//大块内存，直接删除给PageCache
	//如果比128页则直接还给堆
	if (size > MAX_BYTES)
	{

		PageCache::GetInstance()->GetMutex().lock();
		PageCache::GetInstance()->ReleaseSpanToPageCache(span);
		PageCache::GetInstance()->GetMutex().unlock();
	}
	//小于256k，采用三层缓存的删除方式
	else
	{
		assert(pTLSThreadCache);

		pTLSThreadCache->Deallocate(ptr, size);
	}
}
//用来归还ThreadCache的内存
static void Clear()
{
	for (int i = 0; i < NUM_FREE_LIST; ++i)
	{
		if (!pTLSThreadCache->GetFreeList(i).Empty())
		{
			//获取ptr对应的span，然后获取其size
			Span *span = PageCache::GetInstance()->MapObjectToSpan(pTLSThreadCache->GetFreeList(i).GetStart());
			size_t size = span->_objSize;

			CentralCache::GetInstance()->ReleaseListToSpans(pTLSThreadCache->GetFreeList(i).GetStart(), size);
			pTLSThreadCache->GetFreeList(i).Clear();
		}
	}
}